# -*- coding: utf-8 -*-
import websocket
import time
import threading
import json

_py = "Comps/WS.py"

'''
WebSocket客户端模块
'''


class WS:
    def __init__(self, url=None):
        # 连接
        self.url = url

        # 断网重连
        self.if_reconnect = True

        # 心跳包
        self.if_heart = True
        # 客户端发送给服务端心跳包
        self.heart_send = "t"
        self.heart_recv = "t"

        # 重连次数
        self.reconnect_count = 0

        # 回调函数
        self.OnConnect = None
        self.OnRecv = None
        self.OnClose = None

        # 私有
        self.wss = None # 服务主进程
        self.is_thread = True # 主进程循环是否运行
        self.is_create = False # 是否创建成功
        self.is_connect = False # 是否连接服务器成功
        self.is_heart_link = True # 心跳连接是否正常

        self.heart_thread = None
        self.re_thread = None

    # 根据ini的配置项，配置ws客户端
    # [ws]
    # url = ws: // 127.0.0.1: 3300
    # if_reconnect = 1
    # if_heart = 1
    # heart_send = t
    # heart_recv = t
    def setup(self, conf):
        self.url = conf['url']
        self.if_reconnect = bool(conf['if_reconnect'])
        self.if_heart = bool(conf['if_heart'])
        self.heart_send = conf['heart_send']
        self.heart_recv = conf['heart_recv']

    # 创建websocket
    def open(self):
        if not self.url:
            print("WS url为空")
            return

        self.__ws_thread()

        if self.if_heart:
            # 启动心跳包
            if not self.heart_thread:
                self.heart_thread = threading.Thread(target=self.__ws_heart, args=[], daemon=True)
                # self.heart_thread.setDaemon(True)
                self.heart_thread.start()

        if self.if_reconnect:
            # 启动断网重连
            if not self.re_thread:
                self.re_thread = threading.Thread(target=self.__ws_reconnect, args=[], daemon=True)
                # self.re_thread.setDaemon(True)
                self.re_thread.start()

    # websocket进程
    def __ws_thread(self):
        # 启动ws
        ws_thread = threading.Thread(target=self.__ws_run, args=[], daemon=True)
        # ws_thread.setDaemon(True)
        ws_thread.start()

    # websocket启动
    def __ws_run(self):
        wsc = self

        def on_connect(ws):
            wsc.is_connect = True
            if wsc.OnConnect:
                try:
                    wsc.OnConnect()
                except:
                    print("OnConnect错误")

        def on_recv(ws, da):
            wsc.recv(da)

        def on_error(ws, error):
            print("WS运行错误")
            print(error)
            wsc.is_connect = False
            if wsc.is_create and wsc.OnClose:
                try:
                    wsc.OnClose()
                except:
                    print("OnClose错误")

        def on_close(ws):
            wsc.is_connect = False
            if wsc.is_create and wsc.OnClose:
                try:
                    wsc.OnClose()
                except:
                    print("OnClose错误")

        # websocket.enableTrace(True)
        print("【" + _py + "-ws_thread】 启动" + str(self.url))
        self.wss = websocket.WebSocketApp(self.url, on_message=on_recv, on_error=on_error)
        self.is_create = True
        self.wss.on_close = on_close
        self.wss.on_open = on_connect
        self.wss.run_forever()
        print("【err】【" + _py + "-ws_run】 websocket线程结束")

    # 心跳包循环函数
    def __ws_heart(self):
        time.sleep(15)
        while self.is_thread:
            if self.if_heart and self.is_connect:

                if not self.is_heart_link:
                    self.is_heart_link = True
                    # print('未收到心跳包:' + str(self.heart_send))
                    self.is_connect = False

                # print('发送心跳包：' + str(self.heart_send))
                try:
                    self.wss.send(self.heart_send)

                except:
                    print("【err】【" + _py + "-heartbeat】 心跳包错误")
                    self.is_connect = False

            time.sleep(60)
        self.heart_thread = None

    # 断网连接
    def __ws_reconnect(self):
        time.sleep(5)
        while self.is_thread:
            if self.if_reconnect and not self.is_connect:
                try:
                    self.wss.close()
                except:
                    pass
                time.sleep(1)
                print("【err】【" + _py + "-__ws_reconnect】 断网重连")
                self.reconnect_count += 1
                self.__ws_thread()
            time.sleep(5)
        self.re_thread = None

    # 发送
    def send(self, msg):
        if self.is_connect:
            if isinstance(msg, str):
                self.wss.send(msg)
            else:
                self.wss.send(json.dumps(msg))

    # 接收
    def recv(self, da):
        # 心跳包
        if da == self.heart_recv:
            self.is_heart_link = True
            # print("心跳包回馈：" + str(da))
            return

        if self.OnRecv:
            try:
                self.OnRecv(da)
            except:
                print("OnRecv错误")

    # 关闭连接
    def close(self):
        if self.is_connect:
            try:
                self.wss.close()
            except:
                pass

    # 退出
    def exit(self):
        self.is_thread = False
        self.is_create = False
        try:
            self.wss.close()
        except:
            pass
